import { HttpException, Injectable } from '@nestjs/common';
import { CreateInventoryplanDto } from 'src/dto/create-inventoryplan.dto';
import { UpdateInventoryplanDto } from 'src/dto/update-inventoryplan.dto';
import { Inventoryplan } from 'src/entity/inventoryplan.entity';
import { QueryInventoryplanDto } from 'src/dto/query-inventoryplan.dto';
import { parseQueryParams } from 'src/common/utils';
import { Warehouse } from 'src/entity/warehouse.entity';
import { Box } from 'src/entity/box.entity';
import * as dayjs from 'dayjs';
import { Mercadosku } from 'src/entity/mercadosku.entity';

@Injectable()
export class InventoryplanService {
  async create(createInventoryplanDto: CreateInventoryplanDto, uid: number) {
    let warehouse = await Warehouse.findOne({
      where: { id: createInventoryplanDto.warehouseId },
    });

    delete createInventoryplanDto.warehouseId;

    let inventoryplan = Inventoryplan.create({
      ...createInventoryplanDto,
      status: 1,
    });

    // 计算库存数量
    let data = JSON.parse(inventoryplan.data);
    let stock = 0;
    let totalBoxNumber = 0;

    data.map((item: any) => {
      stock += Number(item.boxNumber) * Number(item.number);
      totalBoxNumber += Number(item.number);
    });

    inventoryplan.totalNumber = stock;
    inventoryplan.totalBoxNumber = totalBoxNumber;

    inventoryplan.warehouse = warehouse;
    inventoryplan.adminId = uid;

    return inventoryplan.save();
  }

  async findAll(pageNum: number, pageSize: number) {
    const [list, count] = await Inventoryplan.findAndCount({
      skip: (pageNum - 1) * pageSize,
      take: pageSize,
    });

    return { list, count };
  }

  async query(query: QueryInventoryplanDto) {
    let qeryBuilder = Inventoryplan.createQueryBuilder('inventoryplan');

    let { queryClone, pageNum, pageSize } = parseQueryParams(query, [
      'warehouseId',
    ]);

    qeryBuilder.where(queryClone);

    qeryBuilder.leftJoinAndSelect('inventoryplan.warehouse', 'warehouse');
    qeryBuilder.leftJoinAndSelect('inventoryplan.boxs', 'boxs');
    qeryBuilder.leftJoinAndSelect('boxs.mercadoproduct', 'boxsMercadoproduct');
    qeryBuilder.leftJoinAndSelect('boxs.mercadosku', 'boxsMercadosku');

    // 关联查询
    if (query.warehouseId) {
      qeryBuilder.andWhere('warehouse.id = :warehouseId', {
        warehouseId: query.warehouseId,
      });
    }

    qeryBuilder.skip((pageNum - 1) * pageSize);
    qeryBuilder.take(pageSize);

    qeryBuilder.orderBy('inventoryplan.createTime', 'DESC');

    let [list, count] = await qeryBuilder.getManyAndCount();

    return { list, count };
  }

  findOne(id: number) {
    return Inventoryplan.findOneBy({ id });
  }

  async update(
    id: number,
    updateInventoryplanDto: UpdateInventoryplanDto,
    uid: number,
  ) {
    let warehouse = await Warehouse.findOne({
      where: { id: updateInventoryplanDto.warehouseId },
    });

    delete updateInventoryplanDto.warehouseId;
    let inventoryplan = await Inventoryplan.findOneBy({ id });

    if (inventoryplan.status == 2) {
      throw new HttpException('该计划已运输，不允许修改', 403);
    }

    if (inventoryplan.status == 3) {
      throw new HttpException('该计划已到仓，不允许修改', 403);
    }

    if (inventoryplan.status == 0) {
      throw new HttpException('该计划已作废，不允许修改', 403);
    }

    if (uid == 1 || uid == inventoryplan.adminId) {
      // 计算库存数量
      let data = JSON.parse(inventoryplan.data);
      let stock = 0;
      let totalBoxNumber = 0;

      data.map((item: any) => {
        stock += Number(item.boxNumber) * Number(item.number);
        totalBoxNumber += Number(item.number);
      });

      inventoryplan.totalNumber = stock;
      inventoryplan.totalBoxNumber = totalBoxNumber;

      inventoryplan.totalNumber = stock;

      inventoryplan.warehouse = warehouse;
      await inventoryplan.save();

      await Inventoryplan.update(id, {
        ...updateInventoryplanDto,
        status: 1,
      });
    } else {
      throw new HttpException('没有权限', 403);
    }
  }

  remove(id: number) {
    return Inventoryplan.update(id, { status: 0 });
  }

  async toShipping(id: number) {
    let inventoryplan = await Inventoryplan.findOne({
      where: {
        id,
      },
      relations: {
        warehouse: true,
      },
    });

    let warehouse = inventoryplan.warehouse;

    // 根据inventoryplan计算生成box
    let data = JSON.parse(inventoryplan.data);

    let index = 0;

    let boxs = [];

    // data.map(async (item: any) => {});

    for await (const item of data) {
      let mercadosku = await Mercadosku.findOne({
        where: { id: item.skuId },
        relations: { mercadoproduct: true },
      });

      for (let i = 0; i < Number(item.number); i++) {
        index = index + 1;

        boxs.push({
          name: `QHSM${inventoryplan.id}-${dayjs().format('YYYYMMDD')}-${index}/${inventoryplan.totalBoxNumber}`,
          maitouImage: '',
          boxNumber: item.boxNumber,
          mercadosku,
          mercadoproduct: mercadosku.mercadoproduct,
          warehouse,
          inventoryplan,
        });
      }
    }

    await Box.save(boxs);

    inventoryplan.status = 2;
    return inventoryplan.save();
  }

  async arrive(id: number) {
    let inventoryplan = await Inventoryplan.findOne({
      where: { id },
      relations: { boxs: true },
    });

    let boxs = inventoryplan.boxs;

    for await (const item of boxs) {
      item.status = 1;
      await item.save();
    }

    // 入库时间
    let arrivalTime = new Date();

    // 抵达后每个sku的库存增加
    for await (const item of boxs) {
      let box = await Box.findOne({
        where: { id: item.id },
        relations: { mercadosku: true },
      });

      box.arrivalTime = arrivalTime;

      await box.save();

      // let queryRunner = Mercadosku.createQueryBuilder('mercadosku');
      // queryRunner.where('id = :id', { id: box.mercadosku.id });
      // let mercadosku = await queryRunner.getOne();

      // mercadosku.stock = mercadosku.stock + item.boxNumber;
      // mercadosku.boxNumber = mercadosku.boxNumber + 1;

      // await mercadosku.save();
    }

    inventoryplan.arrivalTime = arrivalTime;
    inventoryplan.status = 3;

    return inventoryplan.save();
  }

  async pay(id: number) {
    let inventoryplan = await Inventoryplan.findOne({
      where: { id },
      relations: { boxs: true },
    });

    let boxs = inventoryplan.boxs;

    // 支付时间
    let payTime = new Date();

    for await (const item of boxs) {
      let box = await Box.findOne({
        where: { id: item.id },
      });

      box.payTime = payTime;
      box.isPay = 1;

      await box.save();
    }

    inventoryplan.payTime = payTime;
    inventoryplan.isPay = 1;

    return inventoryplan.save();
  }
}
